<?php

namespace App\Http\Middleware;

use App\Kuafu\Base\Enum\BaseCodeEnum;
use App\Kuafu\Base\Service\BaseService;
use App\Kuafu\Config\Model\ConfigModel;
use App\Kuafu\User\Enum\CodeEnum;
use App\Kuafu\User\Enum\UserCodeEnum;
use App\Kuafu\User\Model\User;
use App\Kuafu\User\Service\AuthService;
use App\Kuafu\User\Service\NewUserService;
use Closure;
use Kuafu\IpWhite\Service\IpWhiteService;
use Tymon\JWTAuth\Exceptions\JWTException;
use Tymon\JWTAuth\Exceptions\TokenExpiredException;
use Tymon\JWTAuth\Exceptions\TokenInvalidException;
use Tymon\JWTAuth\Http\Middleware\Authenticate;

class JwtAuth extends Authenticate
{
    /**
     * Handle an incoming request.
     *
     * @param \Illuminate\Http\Request $request
     * @param \Closure $next
     * @return mixed
     */
    public function handle($request, Closure $next, $type)
    {
        try {
            // 开发环境不校验，太烦了
            if (config('app.env') == 'dev' && auth('api')->user() == null) {
                $user = User::query()->find(6);
                if ($user) {
                    auth('api')->login($user);
                }
                return $next($request);
            }

            if (config('app.env') == 'qa' && $request->header('kfauth') == '20210717') {
                $user = User::query()->find(6);
                if ($user) {
                    auth('api')->login($user);
                }
                return $next($request);
            }

            //检查请求是否有token
            if (!$this->auth->parser()->setRequest($request)->hasToken()) {
                // 针对 Type = pos 的重新定义报错信息
                switch ($type) {
                    case UserCodeEnum::POS_TYPE:
                        throw new \Exception('POS收银机登录状态异常，请重新登录。', BaseCodeEnum::ERR_TOKEN_ERROR);
                    default:
                        throw new \Exception('登录状态异常，请重新登录。', BaseCodeEnum::ERR_400009);
                }
            }

            //检查token是否过期
            $this->auth->parseToken()->authenticate();

            //判断token是否是当前请求端
            $payload = AuthService::getPayload();
            $payload = $payload->toArray();
            if ($payload['type'] != UserCodeEnum::CODE_TEXT[$type]) {
                throw new \Exception(UserCodeEnum::CODE_TEXT[UserCodeEnum::ERR_USER_PAYLOAD],
                    UserCodeEnum::ERR_USER_PAYLOAD);
            }

            //判断用户帐号状态
            $authUser = AuthService::getAuthUser();
            if ($authUser['status'] != CodeEnum::USER_STATUS_USE) {
                throw new \Exception(UserCodeEnum::CODE_TEXT[UserCodeEnum::ERR_USER_STATUS_STOP],
                    UserCodeEnum::ERR_USER_STATUS_STOP);
            }
            $userId = $authUser->id;
            $ip     = $payload['ip'] ?? '';

            // 商家app、web需要校验ip
            $testerUserIds = json_decode(ConfigModel::getConfigByTypeKeyOne('ipWhite',
                'ipWhiteTestUserIds')['value'] ?? '[]', true);
            (new IpWhiteService($userId, $type, $request))
                ->setIgnoreTypes([UserCodeEnum::APPLET_TYPE, UserCodeEnum::POS_TYPE])
                ->setTesterUserIds($testerUserIds)
                ->checkIp($ip);

            // 用户日活统计
            if ($type == UserCodeEnum::MERCHANT_TYPE) {
                (new NewUserService($userId))->apiIn();
            }

            return $next($request);
        } catch (TokenExpiredException $e) {
            return response()->json(BaseService::returnData(BaseCodeEnum::ERR_400003));
        } catch (TokenInvalidException $e) {
            return response()->json(BaseService::returnData(BaseCodeEnum::ERR_400002));
        } catch (JWTException $ex) {
            return response()->json(BaseService::returnData(BaseCodeEnum::ERR_400009));
        } catch (\Exception $exception) {
            return response()->json(BaseService::returnData($exception->getCode(), $exception->getMessage()));
        }
    }
}
